import {
  Body,
  Controller,
  Get,
  Injectable,
  Module,
  Param,
  Post,
  Request,
} from "@nestjs/common";
import { PrismaClient } from "@prisma/client";
import { WebResult } from "src/common/web.result";
import { ArticleLikeDTO } from "./dto/article-like.dto";
import { ArticleUnlikeDTO } from "./dto/article-unlike.dto";
import { FastifyRequest } from "fastify";
import { InformationService } from "src/common/information.module";

@Injectable()
class ArticleLikeService {
  constructor(private readonly prisma: PrismaClient) {}

  countLike({
    articleID,
    type,
  }: {
    articleID: number;
    type: "like" | "unlike";
  }) {
    return this.prisma.article_like.count({
      where: {
        article_id: articleID,
        type,
      },
    });
  }

  async likeArticle({
    articleID,
    ip,
    type,
  }: {
    articleID: number;
    ip: string;
    type: "like" | "unlike";
  }) {
    const likes = await this.prisma.article_like.findMany({
      where: {
        article_id: articleID,
        ip,
      },
      take: 1,
    });

    // 不存在记录，创建记录
    if (!likes || !likes[0]) {
      await this.prisma.article_like.create({
        data: {
          article_id: articleID,
          ip,
          type,
        },
      });
      return;
    }

    // 类型相同，删除记录
    if (likes[0].type === type) {
      await this.prisma.article_like.deleteMany({
        where: {
          article_id: articleID,
          ip,
        },
      });
      return;
    }

    // 类型不同，修改记录
    await this.prisma.article_like.updateMany({
      data: {
        type,
      },
      where: {
        article_id: articleID,
        ip,
      },
    });
  }
}

@Controller("/article/like")
export class ArticleLikeController {
  constructor(
    private readonly informationService: InformationService,
    private readonly articleLikeService: ArticleLikeService,
  ) {}

  @Get("/count/:id")
  async getCountByArticleID(@Param("id") id: string) {
    const articleID = parseInt(id);
    if (isNaN(articleID)) {
      return WebResult.failure(undefined, "id is not a number");
    }
    const count = await this.articleLikeService.countLike({
      articleID,
      type: "like",
    });
    return WebResult.success(count);
  }

  @Post(["/", "/:id"])
  async like(
    @Request() request: FastifyRequest,
    @Body() likeDTO: ArticleLikeDTO,
    @Param("id") id: string,
  ) {
    const articleID = likeDTO.id || likeDTO.articleID || parseInt(id);
    if (isNaN(articleID)) {
      return WebResult.failure(undefined, "id is not a number");
    }
    try {
      const ip = this.informationService.getIP(request);
      if (!ip) {
        return WebResult.failure(undefined, "点赞失败");
      }

      await this.articleLikeService.likeArticle({
        articleID,
        ip,
        type: "like",
      });
      return WebResult.success(undefined, "点赞成功");
    } catch (e) {
      console.error(e);
      return WebResult.failure(undefined, "内部错误");
    }
  }
}

@Controller("/article/unlike")
export class ArticleUnlikeController {
  constructor(
    private readonly informationService: InformationService,
    private readonly articleLikeService: ArticleLikeService,
  ) {}

  @Get("/count/:id")
  async getCountByArticleID(@Param("id") id: string) {
    const articleID = parseInt(id) || undefined;
    if (isNaN(articleID)) {
      return WebResult.failure(undefined, "id is not a number");
    }
    const count = await this.articleLikeService.countLike({
      articleID,
      type: "unlike",
    });
    return WebResult.success(count);
  }

  @Post(["/", "/:id"])
  async unlike(
    @Request() request: FastifyRequest,
    @Body() unlikeDTO: ArticleUnlikeDTO,
    @Param("id") id: string,
  ) {
    const articleID = unlikeDTO.id || unlikeDTO.articleID || parseInt(id);
    if (isNaN(articleID)) {
      return WebResult.failure(undefined, "id is not a number");
    }
    try {
      const ip = this.informationService.getIP(request);
      if (!ip) {
        return WebResult.failure(undefined, "点踩失败");
      }

      await this.articleLikeService.likeArticle({
        articleID,
        ip,
        type: "unlike",
      });
      return WebResult.success(undefined, "点踩成功");
    } catch (e) {
      console.error(e);
      return WebResult.failure(undefined, "内部错误");
    }
  }
}

@Module({
  controllers: [ArticleLikeController, ArticleUnlikeController],
  providers: [ArticleLikeService],
})
export class ArticleLikeModule {}
